import { toRaw } from "vue"
import { CalcData } from "@/core/calc"
import { CalcFunction, CalcResult } from "@/core/calc"
import { defineStore } from "pinia"
import { useCharacterStore } from "./character"
import { cartesian } from "@/utils"
import { parallel } from "@/utils/async"
import funcs from "@/core/units"

interface CalcState {
    result?: CalcResult
    calculating: boolean
    funcs: CalcFunction[]
}

export const useCalcStore = defineStore("calc", {
    state(): CalcState {
        return {
            result: undefined,
            calculating: false,
            funcs
        }
    },

    getters: {
        // 名望值
        fame(): number {
            return this.result?.context.fame ?? 0
        }
    },

    actions: {
        async calculate_self() {
            let { character, equip_columns } = useCharacterStore()

            if (character) {
                equip_columns = toRaw(equip_columns)
                const rs = (await this.calculate([equip_columns])) ?? []
                this.result = rs.max(e => e.rate)[1]
            }
        },
        async calculate(...args: any[]) {
            const { character } = useCharacterStore()

            if (!character) {
                throw new Error(`not found character.`)
            }
            if (this.calculating) {
                return []
            }

            console.time("calculating")
            this.calculating = true
            console.time("calculating-funcs")

            let calc_matrix = this.funcs.map(func => func(...args))

            console.timeEnd("calculating-funcs")

            calc_matrix = reduce(calc_matrix)

            //   calc_matrix = calc_matrix.filter(e=>e.length)

            calc_matrix = cartesian(...calc_matrix)

            // const rs = calc_matrix.map(e => character.compute_buffer(e))
            const rs = await parallel(calc_matrix, 20, e => character.compute_buffer(e))

            this.calculating = false
            console.timeEnd("calculating")

            return rs
        }
    }
})
///将单一分支合并
export function reduce(matrix: CalcData[][]) {
    const new_matrix: CalcData[][] = []

    let signle: CalcData | undefined = undefined

    function checkSignle() {
        if (signle) {
            new_matrix.push([signle])
            signle = undefined
        }
    }

    for (let array of matrix) {
        if (array.length == 1) {
            if (!signle) {
                signle = new CalcData()
            }
            signle.apply(array[0])
        } else if (array.length > 1) {
            checkSignle()
            new_matrix.push(array)
        }
    }
    checkSignle()
    return new_matrix
}
